package com.apes.fn.crm.customer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.serveControl.serverParentPackage.ServeControl;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.Tools;
import com.apes.pi.service.PiManager;
import com.apes.scm.masterdata.party.model.AccessProvider;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.AccessProviderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.net.URLEncoder;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/***
 * 用于查询
 * 1. 会员数据
 * 2. 会员车辆
 */
@Service("fnAppCustomerService")
public class FnAppCustomerService extends DomainService {

    @Autowired
    private PiManager piManager;

    private boolean paged = true;
    private int page = 0;
    private int size = 20;
    private String sort = null;

    private int requestPage = -1;

    public Object findOneCustomer(SimpleRequest request) {
        JSONObject tempJson = request.getJO();
        if (tempJson.get("mobile") == null) throw new RuntimeException("手机号码不能为空！");

        String QryString;
        if (tempJson.get("vendorCode") == null) {
            QryString = "{\"condition\":[{\"field\":\"mobile\",\"operator\":\"EQ\",\"value\":\"" + tempJson.getString("mobile") + "\"}]}";
        } else {
            QryString = "{\"condition\":[{\"field\":\"mobile\",\"operator\":\"LIKE\",\"value\":\"" + tempJson.getString("mobile")
                    + "\"},{\"field\":\"vendorCode\",\"operator\":\"EQ\",\"value\":\"" + tempJson.getString("vendorCode") + "\"}]}";
        }

        request.setData(QryString);
        JSONObject response = new JSONObject(findAllCustomerCar(request));
        if (response.get("content") != null && response.getJSONArray("content").size() > 0) {
            return response.getJSONArray("content").getJSONObject(0).getJSONObject("customer");
        } else {
            return new JSONObject();
        }
    }


    public Object findOneCustomerCar(SimpleRequest request) {
        JSONObject tempJson = request.getJO();
        if (tempJson.get("carLicense") == null) throw new RuntimeException("车牌号码不能为空！");

        String QryString;
        if (tempJson.get("vendorCode") == null) {
            QryString = "{\"condition\":[{\"field\":\"carLicense\",\"operator\":\"EQ\",\"value\":\"" + tempJson.getString("carLicense") + "\"}]}";
        } else {
            QryString = "{\"condition\":[{\"field\":\"carLicense\",\"operator\":\"EQ\",\"value\":\"" + tempJson.getString("carLicense")
                    + "\"},{\"field\":\"vendorCode\",\"operator\":\"EQ\",\"value\":\"" + tempJson.getString("vendorCode") + "\"}]}";
        }

        request.setData(QryString);
        JSONObject response = new JSONObject(findAllCustomerCar(request));

        if (response.get("content") != null && response.getJSONArray("content").size() > 0) {
            return response.getJSONArray("content").getJSONObject(0);
        } else {
            return new JSONObject();
        }
    }

    /**
     * 查询车辆两次弹框，去除domain参数
     */
    public Map findAllCustomerCarByTwoBulletFrame(SimpleRequest request) {
        JSONObject requestJO = request.getJO();
        if (requestJO.get("domain") != null) {
            requestJO.remove("domain");
            request.setBody(requestJO.toString());
        }
        return findAllCustomerCar(request, true);
    }


    /**
     * 查询车辆
     */
    public Map findAllCustomerCar(SimpleRequest request) {
        return findAllCustomerCar(request, true);
    }


    private Map findAllCustomerCar(SimpleRequest request, boolean isClientPage) {
        String[] fields = FnVendorUserCar.getDeclaredFields();
        Map param = getQueryParams(request, fields, "v1/user/vendor-user-car/index", isClientPage, filter -> true);
        System.out.print(JSON.toJSONString(param));
        JSONObject response = JSONObject.parseObject(this.invoke("pi.app.ext", param));

        return joinCustomerCarToRow(convertResponse(response));
    }

    private Map findAllCustomerCarForControl(SimpleRequest request, boolean isClientPage) {
        String[] fields = FnVendorUserCar.getDeclaredFields();
        Map param = getQueryParams(request, fields, "v1/user/vendor-user-car/index", isClientPage, filter -> true);
        System.out.print(JSON.toJSONString(param));
        JSONObject response = JSONObject.parseObject(this.invoke("pi.app.ext", param));

        return joinCustomerCarToRowForControl(convertResponse(response));
    }


    /**
     * 同步会员身份
     */
    @Deprecated
    public void synVipRole() {
        JSONArray array = new JSONArray();
        array.addAll(getVipRole());
        piManager.synErp("ipmFnVipService.execSynVipRole", MapUtil.mapper("data", array));
    }

    /**
     * 同步会员级别
     */
    @Deprecated
    public void synVipLevel() {
        JSONArray array = new JSONArray();
        array.addAll(getVipLevel());
        piManager.synErp("ipmFnVipService.execSynVipLevel", MapUtil.mapper("data", array));
    }


    /***
     * https://www.yiichina.com/doc/api/2.0/yii-data-datafilter
     *{
     *     "or": [
     *         {
     *             "and": [
     *                 {
     *                     "name": "some name",
     *                 },
     *                 {
     *                     "price": "25",
     *                 }
     *             ]
     *         },
     *         {
     *             "id": {"in": [2, 5, 9]},
     *             "price": {
     *                 "gt": 10,
     *                 "lt": 50
     *             }
     *         }
     *     ]
     * }
     *
     * ['and' => 'AND', 'or' => 'OR', 'not' => 'NOT',
     * 'lt' => '<', 'gt' => '>', 'lte' => '<=', 'gte' => '>=',
     * 'eq' => '=', 'neq' => '!=',
     * 'in' => 'IN', 'nin' => 'NOT IN', 'like' => 'LIKE']
     *
     * 分页状况
     * 1. 下拉查询和弹框查询，分页从零开始
     * 2. 查询界面分页从一开始
     * 3. 后端查询分页返回值从一开始
     * 4. App接口分页从一开始
     * 5. 单查询按后端处理
     *
     * 两种情况：后端数据一致，需处理App接口超过分页数之后的返回值
     * 1. 分页数手动+1
     * 2. 不加
     */
    private Map getQueryParams(SimpleRequest request, String[] fields, String method, Predicate<Filter> predicate) {
        return getQueryParams(request, fields, method, false, predicate);
    }

    private Map getQueryParams(SimpleRequest request, String[] fields, String method, boolean isClientPage, Predicate<Filter> predicate) {
        Map m = request.getMap();
        Map query;

        // 判断是否带分页
        if (m.containsKey("page")) {
            this.requestPage = (int) m.get("page");
            this.size = m.containsKey("size") ? (int) m.get("size") : 20; // 默认分页为20
            if (isClientPage) this.requestPage++;
            query = MapUtil.mapper("perPage", size, "page", this.requestPage, "sort", getSort(), "filter", convertGroup(request, predicate));
        } else {
            this.requestPage = -1;
            query = MapUtil.mapper("filter", convertGroup(request, predicate));
        }
//        {"body": {}, "headers": {"method": "v1/car/index", "action":"get", "returnHeaders":"true"} }
        return MapUtil.mapper(
                "body", MapUtil.mapper("fields", String.join(",", fields), "query", encode(query)),
                "headers", MapUtil.mapper("method", method, "action", "get", "returnHeaders", "true")
        );
    }

    /***
     * 排序
     * @return
     */
    private String getSort() {
        if (StringUtils.isEmpty(this.sort)) return null;
        StringBuffer stringBuffer = new StringBuffer();
        String[] sorts = this.sort.split(",");

        for (int i = 0, length = sorts.length; i < length; i++) {
            String[] order = StringUtils.split(sort.trim(), " ");
            if (order.length == 1) {
                stringBuffer.append("+" + order[0].trim()); // asc
            } else {
                if (order[1].trim().equalsIgnoreCase("desc")) {
                    stringBuffer.append("-" + order[0].trim()); // desc
                } else {
                    stringBuffer.append("+" + order[0].trim()); // asc
                }
            }
        }
        return stringBuffer.toString();
    }

    /***
     * 获取查询条件
     */
    private Map convertGroup(SimpleRequest request, Predicate<Filter> predicate) {
        Group group;
        if (request.getData() instanceof Group) {
            group = Tools.map(request.getData(), Group.class);
        } else {
            group = JpaDsl.getGroup(request);
        }
        // 额外拼接接入商字段
        group = initQuery(group, request);

        return convertGroup(group, predicate);
    }


    private Map convertGroup(Group group, Predicate<Filter> predicate) {
        if (group == null) return new HashMap();
        Map build = new HashMap();
        List groupList = new ArrayList();
        List filterList = new ArrayList();
        group.getFilters().stream()
                .filter(filter -> predicate.test(filter))
                .map(filter -> convertFilter(filter))
                .forEach(filter -> filterList.add(filter));
        List<Map> groupMap = group.getGroups().stream().map(groupTemp -> convertGroup(groupTemp, predicate)).collect(Collectors.toList());
        groupList.addAll(filterList);
        groupList.addAll(groupMap);
        build.put(group.getOperator(), groupList);
        return build;
    }


    private Map convertFilter(Filter filter) {
        if (filter == null) return new HashMap();
        String operator;
        switch (filter.getOperator()) {
            case "LIKE":
                operator = "like";
                break;
            case "EQ":
                operator = "eq";
                return MapUtil.mapper(filter.getField(), filter.getValue());
            default:
                throw new RuntimeException("不支持的操作符号:" + filter.getOperator() + "请手动扩展");
        }
        return MapUtil.mapper(filter.getField(), MapUtil.mapper(operator, filter.getValue()));
    }

    private String encode(Map map) {
        try {
            return URLEncoder.encode(JSON.toJSONString(map), "UTF-8");
        } catch (Exception e) {
            throw new RuntimeException("请求失败，请确认请求数据");
        }
    }

    /***
     * 转换返回值（一般格式化）
     */
    private Map convertResponse(JSONObject param) {
        if (param == null) return null;
        JSONObject body, headers;
        try {
            body = param.getJSONObject("body");
            headers = param.getJSONObject("headers");
        } catch (Exception e){
            throw new RuntimeException("调用接口报错,返回值为:" + JSON.toJSONString(param));
        }
        JSONArray data = new JSONArray();
        try{
            data= body.getJSONArray("data");
        }catch (Exception e){
            JSONObject bodyJSONObject = body.getJSONObject("data");
            String message = bodyJSONObject.getString("message");
            throw new RuntimeException(message+"[APP]");
        }


        try {
            if (body.getBooleanValue("success")) {
                // 处理超出查询页数后依然返回数据的问题
                if (this.requestPage > headers.getIntValue("X-Pagination-Page-Count")) {
                    return MapUtil.mapper(
                            "content", new ArrayList(),
                            "elements", 0,
                            "page", headers.getIntValue("X-Pagination-Page-Count"),
                            "pages", headers.getIntValue("X-Pagination-Page-Count"),
                            "size", headers.getIntValue("X-Pagination-Per-Page"),
                            "total", headers.getIntValue("X-Pagination-Total-Count")
                    );
                }

                return MapUtil.mapper(
                        "content", data,
                        "pages", headers.getIntValue("X-Pagination-Page-Count"),
                        "page", headers.getIntValue("X-Pagination-Current-Page") - 1,
                        "size", headers.getIntValue("X-Pagination-Per-Page"),
                        "total", headers.getIntValue("X-Pagination-Total-Count"),
                        "elements", data.size()
                );
            } else {
                throw new RuntimeException(body.getJSONArray("data").getJSONObject(0).getString("message")+"[APP]");
            }
        } catch (Exception e) {
            throw new RuntimeException(body.getJSONArray("data").getJSONObject(0).getString("message")+"[APP]");
        }

    }

    /***
     * 查询界面格式化
     */
    private Map convertResponseForQueryPage(JSONObject param) {
        return MapUtil.mapper(
                "content", param.getJSONArray("content"),
                "page", param.getIntValue("pages"),
                "size", param.getIntValue("size"),
                "total", param.getIntValue("total"),
                "gridheader", null
        );
    }

    /***
     * 初始化单查询
     */
    private void initQuery(SimpleRequest request) {
        this.page = 1;
        this.size = 1;
        this.requestPage = 1;
        Map m = request.getMap();
        if (!m.containsKey("condition") && !m.containsKey("group")) {
            convertMapToGroup(request);
        }
    }

    private void convertMapToGroup(SimpleRequest request) {
        Group group = new Group();
        List<Filter> filters = new ArrayList();
        Map items = request.getMap();
        items.forEach((k, v) -> {
            Map row = new HashMap();
            row.put("field", k);
            row.put("value", v);
            row.put("operator", "EQ");
            filters.add(Tools.toBean(Filter.class, row));
        });
        group.setOperator("and");
        group.setFilters(filters);
        request.setData(group);
    }


    /***
     * 查询条件拼接接入商字段
     */
    private Group initQuery(Group group, SimpleRequest request) {
        String str = JSON.toJSONString(group);
        Group containGroup = new Group();

        if (!str.contains("vendorCode") && request.getJO().get("vendorCode") == null&&!str.contains("ven")) {
            containGroup.setOperator("and");

            // 拼接对应的接入商信息
            PartyRole company = request.getCurrentCompany();

            if (company == null) throw new RuntimeException(
                    "该接口需提供对应的接入商编码，并赋值给vendorCode字段，若为前端调用请确认是否传入对应的session，" + "若为后端调用请在查询条件传入会员扩展表的接入商字段");

            AccessProvider accessProvider = company.queryAccessProvider();
            if (accessProvider == null) throw new RuntimeException("该接口需提供对应的接入商编码，当前公司下未找到对应的接入商,公司编码:" + company.getId());


            containGroup.addFilters(JpaDsl.toFilter("vendorCode", "EQ",
                    (company.queryAccessProvider().getId())));
            group.setGroups(new ArrayList<>());
            containGroup.addGroup(group);
            return containGroup;
        } else {
            if (str.contains("ven")){
                List<Filter> filters = group.getFilters();
                for (int i = 0; i < filters.size(); i++) {
                    if (filters.get(i).getField().equals("ven")) {
                        filters.remove(i);
                        i--;
                    }
                    group.setFilters(filters);
                }
                List<Group> groups = group.getGroups();
                for (int i = 0; i < groups.size(); i++) {
                    List<Filter> filterList = groups.get(i).getFilters();
                    for (int j = 0; j < filterList.size(); j++) {
                        if (filterList.get(j).getValue().equals("")) {
                            filterList.remove(j);
                            j--;
                        }else if (filterList.get(j).getField().equals("ven")) {
                            filterList.remove(j);
                            j--;
                        }

                    }
                    if (filterList.isEmpty()){
                        groups.remove(i);
                        i--;
                    }else {
                        groups.get(i).setFilters(filterList);
                    }

                }
            }
            return group;
        }
    }

    /***
     * 查询会员身份
     */
    private JSONArray getVipRole() {
        Map param = MapUtil.mapper("body", new JSONObject(),
                "headers", MapUtil.mapper("method", "v1/user/user-role/index", "action", "get"));
        JSONObject response = JSONObject.parseObject(this.invoke("pi.app.ext", param));

        if (response != null && response.getBooleanValue("success") &&
                response.get("data") != null && response.getJSONArray("data").size() > 0) {
            return response.getJSONArray("data");
        } else {
            return new JSONArray();
        }
    }


    /***
     * 查询会员级别
     */
    private JSONArray getVipLevel() {
        Map param = MapUtil.mapper(
                "body", MapUtil.mapper("theme", "vendor.user.level"),
                "headers", MapUtil.mapper("method", "v1/common-option?theme", "action", "get"));

        JSONObject response = JSONObject.parseObject(this.invoke("pi.app.pub", param));
        if (response != null && response.getBooleanValue("success") &&
                response.get("data") != null && response.getJSONArray("data").size() > 0) {
            return response.getJSONArray("data");
        } else {
            return new JSONArray();
        }
    }

    /***
     * 处理会员车辆,将车辆和会员拼接为一行数据
     */
    private Map joinCustomerCarToRow(Map param) {
        JSONObject paramJson = new JSONObject(param);
        JSONArray array = new JSONArray();
        paramJson.getJSONArray("content").stream().forEach(
                content -> {
                    JSONObject contentJson = (JSONObject) content;
                    JSONObject tempJson = new JSONObject();
                    tempJson.put("vendorCode", contentJson.getString("vendorCode"));
                    tempJson.put("vendorName", contentJson.getString("vendorName"));
                    tempJson.putAll(contentJson.get("carArchive") != null ? contentJson.getJSONObject("carArchive") : new HashMap());
                    tempJson.put("carLicense", contentJson.get("carLicense"));

                    tempJson.put("customer", contentJson.get("vendorUser"));
                    tempJson.put("realname", contentJson.get("vendorUser") != null ? contentJson.getJSONObject("vendorUser").getString("realname") : "");
                    tempJson.put("mobile", contentJson.get("vendorUser") != null ? contentJson.getJSONObject("vendorUser").getString("mobile") : "");
                    tempJson.put("levelLabel", contentJson.get("vendorUser") != null ? contentJson.getJSONObject("vendorUser").getString("levelLabel") : "");
                    tempJson.put("activit", contentJson.get("vendorUser") != null ? contentJson.getJSONObject("vendorUser").getString("activit") : "");
                    tempJson.put("activityLabel", contentJson.get("vendorUser") != null ? contentJson.getJSONObject("vendorUser").getString("activityLabel") : "");

                    tempJson.put("userRoleName", contentJson.get("vendorUser") != null && contentJson.getJSONObject("vendorUser").get("userRole") != null ?
                            contentJson.getJSONObject("vendorUser").getJSONObject("userRole").getString("name") : null);
                    if (contentJson.get("carArchive") != null){
                        JSONObject baseInfo = SpringManager.getBean(FnApiService.class).getCarServiceLevel(contentJson.getJSONObject("carArchive").getString("jekunModelCode"));
                        String carBase = baseInfo.getString("CarServiceLevelName");
                        if(baseInfo.getString("validFlag")!=null)tempJson.put("validFlag",baseInfo.getString("validFlag"));
                        if(baseInfo.getString("carModel")!=null)tempJson.put("carModel",baseInfo.getString("carModel"));
                        if(baseInfo.getString("YXBJ")!=null)tempJson.put("validFlag",getValidFlag(baseInfo.getString("YXBJ")));
                        if (carBase!=null&&!carBase.equals(""))tempJson.put("carServiceLevel","["+carBase+"]");
                    }
                    array.add(tempJson);
                }
        );
        param.put("content", array);
        return param;
    }

    public void checkCarModelValid(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONObject baseInfo = SpringManager.getBean(FnApiService.class).getCarServiceLevel(jo.getString("jekunModelCode"));

        if(baseInfo.getString("validFlag")!=null&&"invalid".equals(baseInfo.getString("validFlag")))
            throw new RuntimeException("当前车型无效，请去服务管理页->车辆信息页面  修改车型数据后再创建接车");
        if(baseInfo.getString("YXBJ")!=null&&"0".equals(baseInfo.getString("YXBJ")))
            throw new RuntimeException("当前车型无效，请去服务管理页->车辆信息页面  修改车型数据后再创建接车");
    }

    private String getValidFlag(String strNum) {
        switch (strNum) {
            case "1":
                return "valid";
            case "0":
                return "invalid";
            case "10":
                return "stopService";
            default:
                return "valid";
        }
    }


    /***
     * 处理会员车辆,将车辆和会员拼接为一行数据
     */
    private Map joinCustomerCarToRowForControl(Map param) {
        JSONObject paramJson = new JSONObject(param);
        JSONArray array = new JSONArray();
        paramJson.getJSONArray("content").stream().forEach(
                content -> {
                    JSONObject contentJson = (JSONObject) content;
                    JSONObject tempJson = new JSONObject();
                    tempJson.put("carLicense", contentJson.getString("carLicense"));
                    tempJson.put("realname", contentJson.get("vendorUser") != null ? contentJson.getJSONObject("vendorUser").getString("realname") : "");
                    tempJson.put("mobile", contentJson.get("vendorUser") != null ? contentJson.getJSONObject("vendorUser").getString("mobile") : "");
                    tempJson.put("id", MapUtil.mapper("carLicense",tempJson.getString("carLicense"),"realname",tempJson.getString("realname"),"mobile",tempJson.getString("mobile")));
                    array.add(tempJson);
                }
        );
        param.put("content", array);
        return param;
    }


    public Page<Map> qryCarliscenceForControl(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONObject param = new JSONObject();
        param.put("SIZE", request.get("size"));
        param.put("PAGE", request.get("page"));
        if(jo.get("key") != null){
            param.put("conditon",jo.getString("key"));
        }
        JSONArray array = SpringManager.getBean(ServeControl.class).qryCarliscenceForControl(param);
        List resultList = array.stream().map(item ->{
            JSONObject itemJson = (JSONObject)item;
            return MapUtil.mapper("id",itemJson.getString("CAR_LICENSE"),
                    "CAR_LICENSE",itemJson.getString("CAR_LICENSE"),
                    "REALNAME",itemJson.getString("REALNAME"),
                    "MOBILE",itemJson.getString("MOBILE")
            );
        }).collect(Collectors.toList());
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"), sort);
        PageImpl<Map> pPage = new PageImpl<>(resultList, pageable, array.size() == 0 ?
                0 : array.getJSONObject(0).getIntValue("TOTAL"));
        return pPage;
    }

    /**
     * 服务方案单弹窗图片
     * @param request
     * @return
     */
    public String getPictures(SimpleRequest request){
        JSONObject oneCustomerCar = (JSONObject)findOneCustomerCar(request);
        JSONArray pictures = new JSONArray();
        if (!Objects.isNull(oneCustomerCar.getJSONObject("pic1"))){
            pictures.add(MapUtil.mapper("url", oneCustomerCar.getJSONObject("pic1").getString("path")));
        }
        if (!Objects.isNull(oneCustomerCar.getJSONObject("pic2"))){
            pictures.add(MapUtil.mapper("url", oneCustomerCar.getJSONObject("pic2").getString("path")));
        }
        if(!Objects.isNull(oneCustomerCar.getJSONObject("pic38"))){
            pictures.add(MapUtil.mapper("url", oneCustomerCar.getJSONObject("pic38").getString("path")));
        }
        return pictures.toJSONString();
    }
}

